#include <render/UI/text/text.h>
#include <render/UI/text/font.h>

#include <string>
#include <freetype2/ft2build.h>
#include <glm/glm.hpp>
#include <render/output/shader.h>

Text::Text(std::string& str, float scale, glm::vec2 pos, glm::vec3 color, uint32_t matrix_w, uint32_t matrix_h)
{
	this->m_text = str;
	this->m_scale = scale;
	this->m_pos = pos;
	this->m_color = color;
	this->m_projection = glm::ortho(0.0f, static_cast<float>(matrix_w), 0.0f, static_cast<float>(matrix_h));
	this->m_shader->Bind();
	glUniformMatrix4fv(glGetUniformLocation(this->m_shader->GetProgram(), "projection"), 1, GL_FALSE, glm::value_ptr(this->m_projection));
}

void Text::Print () {
	if(this->m_text.empty())
	{
		return;
	}

    this->m_shader->Bind();
    glUniform3f(glGetUniformLocation(this->m_shader->GetProgram(), "textColor"),
    								 this->m_color.x,
    								 this->m_color.y,
    								 this->m_color.z);

    glUniform1f(glGetUniformLocation(this->m_shader->GetProgram(), "transparency"), this->m_transparency);
    glActiveTexture(GL_TEXTURE0);
    glBindVertexArray(this->VAO);

    std::string::const_iterator c;
    for (c = this->m_text.begin(); c != this->m_text.end(); c++)
    {
        ft_char_t ch = this->m_font.alphabet[*c];

        GLfloat xpos = this->m_pos.x + ch.bearing.x * this->m_scale;
        GLfloat ypos = this->m_pos.y - (ch.size.y - ch.bearing.y) * this->m_scale;

        GLfloat w = ch.size.x * this->m_scale;
        GLfloat h = ch.size.y * this->m_scale;

        GLfloat vertices[6][4] = {
            { xpos, ypos + h, 0.0, 0.0 },
            { xpos, ypos, 0.0, 1.0 },
            { xpos + w, ypos, 1.0, 1.0 },
            { xpos, ypos + h, 0.0, 0.0 },
            { xpos + w, ypos, 1.0, 1.0 },
            { xpos + w, ypos + h, 1.0, 0.0 }
        };

        glBindTexture(GL_TEXTURE_2D, ch.textureID);

        glBindBuffer(GL_ARRAY_BUFFER, this->VBO);
        glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
        glBindBuffer(GL_ARRAY_BUFFER, 0);

        glDrawArrays(GL_TRIANGLES, 0, 6);

        this->m_pos.x += (ch.advance >> 6) * this->m_scale;
    }
    glBindVertexArray(0);
    glBindTexture(GL_TEXTURE_2D, 0);
}
